Nella Sessione 5, avete incontrato il modello di un'industria di produzione che usava impianti multipli per produrre i propri prodotti. Quello che dovreste notare a proposito del modello è che, mentre ogni impianto potrebbe essere usato per produrre prodotti individualmente, tutte le vendite e gli inventari sono stati trattati collettivamente, come una fonte singola, per l'intera industria. Ora aggiornerete quel modello per far sì che ogni impianto venda i prodotti, e effettui individualmente l'inventario. Inoltre, al fine di compiere la richiesta nella maniera più efficiente, i prodotti possono essere spediti tra gli impianti come da bisogno.
Per aggiornare il modello avrete bisogno di includere due nuovi indici fittizi, toplant, e fromplant, che rappresenteranno la fonte e gli impianti di destinazione. Aggiornerete, inoltre, le variabili Inventory e Sales per includere l'indice plant, così che ogni impianto possa ora vendere i prodotti e mantenere ogni inventario indipendente dall'altro.
I Modelli che permettono la spedizione tra diversi luoghi sono a volte chiamati modelli di trasporto o distribuzione. Tipicamente, nei modelli di trasporto, avete punti di partenza con una certa disponibilità, destinazioni con determinati requisiti, e avete bisogno di spedire i prodotti da questi punti di partenza a queste destinazioni. In alcuni casi, avete modelli di trasporto con livelli multipli.Per esmpio, ci possono essere carichi da impianti a depositi, e poi dai depositi a negozi di vendita al dettaglio.
Un altro gruppo di modelli di distribuzione sono i modelli di transshipment(trasbordo). Questi modelli si presentano, tipicamente, quando si hanno posizioni multiple che producono entrambe beni e fungono, inoltre, come centri di richiesta. Fin qui non ci sono punti di partenza specifici o destinazioni, potete trasportare da qualsiasi posizione ad un 'altra.
Gli Indici Fittizi sono utili quando si deve definire un vettore, che usa lo stesso indice più di una volta, come sottoscritto. Quando trasportate prodotti tra impianti avete bisogno di creare un vettore di variabile, che rappresenti quanto trasportare tra gli impianti. Dato che gli impianti di partenza e gli impianti di destinazione vengono dallo stesso set d'impianti, avete bisogno di due indici fittizi per gli impianti. Il primo indice fittizio deve rappresentare gli impianti di partenza, e il secondo deve rappresentare quelli di destinazione.
A volte, quando si lavora con variabili di vettore multi-dimensionale si incontrano casi in cui non tutti gli elementi del vettore sono validi, o hanno un significato.Per esempio, nel modelli di trasbordo avrebbe poco senso trasportare un prodotto da un certo impianto verso quello stesso. In questi casi, si può usare la condizione WHERE(DOVE) sulla variabile per rimuovere elementi non necessari.
Per esempio, in un modello di trasbordo potete eliminare la possibilità di trasportare alla stessa posizione definendo la variabile come segue:
VARIABLES Ship[fromplant,toplant] WHERE (fromplant <> toplant);
In questo caso, la condizione (fromplant <> toplant) elimina tutti gli elementi di vettore, dove l'impianto di partenza è lo stesso di quello di destinazione.
In alcuni casi, gli elementi, che nono sono basati su valori degli indici, devono essere esclusi. Questi, dunque, devono essere basati su alcuni vettori di dati nel modello.Tipicamente, avete un vettore di costo che contiene quanto costa il trasporto tra impianti. Per questi impianti, se il trasporto non è possibile, potete introdurre un valore speciale per il costo, come zero, che venga usato per identificarli. Dunque, nella definizione della variabile, potete usare questo vettore di dati per escludere gli itinerari di spedizione che non sono possibili come segue:
VARIABLES Ship[fromplant,toplant] WHERE (ShipCost[fromplant,toplant] > 0);
Quando si lavora con modelli di trasbordo si deve essere sicuri che la quantità dei prodotti spediti all'impianto, più quanto è prodotto e considerato nell' inventario sia uguale a quanto è trasportato dall'impianto, più quanto è venduto e rimesso nell'inventario . In breve, tutto ciò che va all' impianto deve essere uguale a tutto ciò che esce dall'impianto. Questio tipo di vincolo è tipicamente chiamato vincolo d'equilibrio d'impianto. Qui trovate un esempio di un semplice vincolo di equilibrio d' impianto:
PlantBal[plant, product, month]: Produce + Inventory[month-1] + SUM(fromplant: Ship[fromplant, toplant:=plant]) = Sales + Inventory + SUM(toplant: Ship[fromplant:=plant, toplant]);
Noterete che questo vincolo è simile al vincolo d'equilibrio dell'inventario che avete incontrato nella sessione precedente. L'unica differenza è che ora dovete tenere conto che stiamo trasportando a e da ogni impianto introducendo una sommatoria su ogni impianto per la variabile Ship (Imbarco).
Il compito dell'indice 'toplant:=plant', nella prima sommatoria, ci permette di specificare che il sottoscritto toplant dovrebbe prendere il valore del sottoscitto plant per il vincolo PlantBal. Questa sommatoria somma tutti i carichi da ogni impianto ad un particolare impianto in quel vincolo. In una maniera simile, l'assegnazione dell' indice 'fromplant:=plant', nella seconda sommatoria, specifica che il sottoscritto fromplant dovrebbe prendere il valore del sottoscritto plant.
In questa sessione, verrà creato un nuovo modello in cui ogni impianto lavorerà, ora, come centro sparato di richiesta per i prodotti, e può inoltre mantenere l'inventario. Si userà il modello che avete creato nella Sessione 5, facendo le necessarie aggiunte e aggiornamenti su di esso.
Dato che ogni impianto può vendere i prodotti, noi ora abbiamo una differente richiesta per ogni impianto, come per ogni prodotto, e per ogni mese. La richiesta viene data nella tabella sottostante:
Plant | Product | Jan | Feb | Mar | Apr |
---|---|---|---|---|---|
p1 | A1 | 4300 | 4200 | 6400 | 5300 |
A2 | 4500 | 5400 | 6500 | 7200 | |
A3 | 5400 | 6700 | 7800 | 8200 | |
p2 | A1 | 5100 | 6200 | 5400 | 7600 |
A2 | 6300 | 7100 | 5200 | 6300 | |
A3 | 4800 | 6500 | 5000 | 7200 | |
p3 | A1 | 4100 | 6100 | 4700 | 5800 |
A2 | 5300 | 5200 | 5700 | 4100 | |
A3 | 4200 | 4100 | 5200 | 6300 | |
p4 | A1 | 4300 | 4100 | 5300 | 4500 |
A2 | 5300 | 6400 | 4200 | 6200 | |
A3 | 5600 | 5200 | 3800 | 4100 |
Questi dati possiedono tre dimensioni, impianti, prodotti e mesi. Nei modelli di programmazione lineare è abbastanza tipico avere dati con dimensioni multiple, possibilmente fino ad otto o più. Nella prossima Sessione, aggiorneremo i dati della richiesta così da includere una dimensione in più; le macchine , creando un vettore a quattro dimensioni.
La capacità dell'inventario è ora differente per ogni impianto. Abbiamo quattro valori di capienza d'inventario, uno per ogni impianto 800, 400, 500, e 400 rispettivamente.
Dato che ora abbiamo impianti multipli, ciascuno dei quali possa mantenere l'inventore, noi ora abbiamo differenti costi per ogni impianto, e per ogni prodotto. I nuovi valori di costo per l'inventario sono mostrati qui sotto:
Inventory Cost | A1 | A2 | A3 |
---|---|---|---|
p1 | $8.50 | $7.00 | $6.50 |
p2 | $9.80 | $9.80 | $9.80 |
p3 | $7.50 | $7.50 | $7.50 |
p4 | $9.30 | $8.00 | $6.50 |
Alla fine, dato che stiamo permettendo spedizioni tra gli impianti ci sono alcuni costi coinvolti per il trasporto di un prodotto, come mostrato nella tabella di sotto:
Shipping Cost | p1 | p2 | p3 | p4 |
---|---|---|---|---|
p1 | - | $15.00 | $21.00 | $13.00 |
p2 | $16.00 | - | $12.00 | $12.00 |
p3 | $14.00 | $17.00 | - | $15.00 |
p4 | $21.00 | $13.00 | $10.00 | - |
Come si può notare, non ci sono valori nella tabella dove l'impianto di partenza è lo stesso dell'impianto di destinazione. Questo perchè non esiste alcun beneficio nel trasportare indietro all' ipianto di partenza.
Elencata qui, di seguito, troverete l'intera formulazione del modello per Planning6. Le aggiunte al modello sono sottolineate in neretto al fine di rendere più semplice la lettura dei cambiamenti dal modello della Sessione 5.
TITLE Production_Planning6; INDEX product := (A1, A2, A3); month := (Jan, Feb, Mar, Apr); plant := (p1, p2, p3, p4); fromplant := plant; toplant := plant; DATA Price[product] := (120.00, 100.00, 115.00); Demand[plant, product, month] := DATAFILE("Demand6.dat"); ProdCost[plant, product] := DATAFILE("ProdCost.dat"); ProdRate[plant, product] := DATAFILE("ProdRate.dat"); ProdDaysAvail[month] := (23, 20, 23, 22); InvtCost[plant, product] := DATAFILE("InvtCost.dat"); InvtCapacity[plant] := (800, 400, 500, 400); ShipCost[fromplant, toplant] := DATAFILE ("ShipCost.dat"); VARIABLES Produce[plant, product,month] -> Prod; Inventory[plant, product, month] -> Invt; Sales[plant,product, month] -> Sale; Ship[product, month, fromplant, toplant] WHERE (fromplant <> toplant); MACROS TotalRevenue := SUM(plant, product,month: Price * Sales); TotalProdCost := SUM(plant, product, month: ProdCost* Produce); TotalInvtCost := SUM(plant, product, month: InvtCost * Inventory); TotalShipCost := SUM(product, month, fromplant,toplant: ShipCost * Ship); TotalCost := TotalProdCost + TotalInvtCost + TotalShipCost; MODEL MAX Profit= TotalRevenue - TotalCost; SUBJECT TO ProdCapacity[plant, month] ->PCap: SUM(product: Produce / ProdRate) <= ProdDaysAvail; PlantBal[plant, product, month] -> PBal: Produce + Inventory[month-1] + SUM(fromplant:Ship[fromplant, toplant:=plant]) = Sales + Inventory + SUM(toplant: Ship[fromplant:=plant,toplant]); MaxInventory[plant, month] -> MaxI: SUM(product: Inventory) <= InvtCapacity; BOUNDS Sales < Demand ; END
Eseguire l'applicazione MPL.
Scegliere File (Archivio)| Open (Aprire) e aprire il modello dalla sessione precedente Planning5.mpl.
Scegliere File (Archivio)| Save As (Salvare come) per salvare il nuovo file di modello Planning6.mpl.
Cambiare il Titolo al Modello per sottolineare che state lavorando con il modello Planning6:
TITLE Production_Planning6;
In questa sessione, state per aumentare il modello per permettere spedizioni tra gli impianti. Gli Indici Fittizi sono utili quando dovete definire un vettore, che si riferisce allo stesso indice più di una volta, come sottoscritto. Gli indici fittizi sono una copia esatta dell'indice precedentemente definito.
In questo caso, state creando una variabile di vvettore che rappresenti quanto trasportare tra gli impianti. Questo significa che avete bisogno di due indici fittizi per rappresentare gli impianti di partenza e di destinazione. Aggiungere le seguenti definizioni per i due nuovi indici fittizi che chiamerete fromplant e toplant alla fine della sessione INDEX:
INDEX product := (A1, A2, A3); month := (Jan, Feb, Mar, Apr); plant := (p1, p2,p3, p4); fromplant := plant; toplant := plant;
Abbiamo ora una differente richiesta per ogni impianto. La definizione per il vettore di dati Demand necessita di essere aggiornata così da includere l'indice plant. Nell'editor del modello, aggiungere l'indice plant al vettore di dati Demand e cambiare il nome del file in Demand6.dat.
DATA Price[product] := (120.00, 100.00, 115.00); Demand[plant, product, month] := DATAFILE("Demand6.dat");
Dato che il vettore Demand ora ha tre indici, il file di dati per esso necessita di essere aggiornato. Quindi, create un nuovo file di dati chiamato 'Demand6.dat' usando i valori di dati dalla tabella nella descrizione del problema forniti, prima, in questa sessione. Introdurre i valori di dati nel file di dati come segue:
! ! Demand6.dat - Demand for each product and each plant ! ! Demand[plant,product,month]: ! ! Jan Feb Mar Apr ! --------------------------- !plant 1: 4300, 4200, 6400, 5300, 4500, 5400, 6500, 7200, 5400, 6700, 7800, 8200, !plant 2: 5100, 6200, 5400, 7600, 6300, 7100, 5200, 6300, 4800, 6500, 5000, 7200, !plant 3: 4100, 6100, 4700, 5800, 5300, 5200, 5700, 4100, 4200, 4100, 5200, 6300, !plant 4: 4300, 4100, 5300, 4500, 5300, 6400, 4200, 6200, 5600, 5200, 3800, 4100
Quando avete dati a tre dimansioni nei files, elencate i loro valori nello stesso ordine in cui sono stati definiti gli indici nel vettore di dati per il modello. Per esempio, nel sovrastante file di dati Demand6, l'indice più a sinistra è l'indice plant, seguito dall'indice producte dall'indice month.
Dato che, ora, potete immagazzinare l'inventario ad ogni impianto, avete bisogno di aggiornare il costo dell'inventario e i dati di capienza dell'inventario per includere l'indice plant. Nell'editor del modello, aggiungere l'indice plant alla dichiarazione del vettore di dati InvtCost e alla costante di dati InvtCapacity. Poi, per il vettore di dati InvtCost rimuovere la lista di numeri e rimetterla con la parola chiave DATAFILE e con il nome del file 'InvtCost.dat.' Per la InvtCapacity togliere il valore singolo 800 e rimetterlo con la list di quattro valori, uno per ogni impianto, presi dalla descrizione del problema precedentemante in questa sessione.
InvtCost[plant, product] := DATAFILE("InvtCost.dat"); InvtCapacity[plant] := (800, 400, 500, 400);
In seguito, dovete creare un nuovo file di dati chiamato 'InvtCost.dat' usando i valori del costo dalla tabella del cost dell'inventario nella descrizione del problema. Introdurre i valori dei dati nel file di dati come segue:
! ! InvtCost.dat - Inventory cost per item a month ! ! InvtCost[plant,product]: ! ! A1 A2 A3 ! ----------------------- 8.50, 7.00, 6.50 9.80, 9.80, 9.80 7.50, 7.50, 7.50 9.30, 8.00, 6.50
Ci sono certi costi coinvolti nel trasporto dei prodotti tra impianti. Nell'editor del modello, aggiungere un nuovo vettore di dati chiamato ShipCost definito su i due indici fittizi fromplant e toplant segiuto dalla parola chiave DATAFILE e dal nome del file ShipCost.dat.
ShipCost[fromplant, toplant] := DATAFILE("ShipCost.dat");
Successivamente dovete creare un nuovo file di dati chiamato ShipCost.dat che contenga le figure di costo per il trasporto tra impianti fornite nella descrizione del problema. Introdurre i valori dei dati per il file di dati come segue:
! ! ShipCost.dat - Shipping costs from plant to plant ! ! ShipCost[fromplant, toplant] ! 0, 15.00, 21.00, 13.00, 16.00, 0, 12.00, 12.00, 14.00, 17.00, 0, 15.00, 21.00, 13.00, 10.00, 0,
Stiamo rendendo possibile il trasporto tra impianti, perciò, si deve creare una nuova variabille che decida quanto deve essere trasportato di ogni prodotto al mese. Questo vettore di variabile sarà definito sugli indici fittizi fromplant e toplant come gli indici product e month. Aggiungere la seguente definizione per il vettore di variabile Ship alla sezione VARIABLES:
Ship[product, month, fromplant, toplant] WHERE (fromplant <> toplant);
Dato che non vogliamo trasportare un prodotto da un impianto all'impianto stesso, usiamo la condizione WHERE per rimuovere tutti gli elementi di vettore in cui l'impianto di partenza è lo stesso di quello di destinazione.
Nella sezione MACROS aggiungere una nuova definizione macro per il costo totale del trasporto chiamata TotalShipCost e aggiorniamo la macro TotalCost per includere la nuova macro come segue:
TotalShipCost := SUM(product, month, fromplant, toplant: ShipCost * Ship); TotalCost := TotalProdCost + TotalInvtCost + TotalShipCost;
Si noti che l'attuale definizione della funzione obiettivo non ha bisogno di essere cambiata in quanto la macro TotalCost contiene tutti i cambiamenti.
Dato che ora abbiamo permesso trasporti tra impianti, si deve aggiornare il vincolo d'equilibrio dell'inventario dal modello precedente ad un vincolo d'equilibrio d'impianto. Come prima cosa, cambiare il nome del vincolo da InvtBala PlantBal e aggiungere l'indice plant alla dichiarazione. Di seguito, dato che il vincolo, ora, è dichiarato, non dobbiamo più sommare l'indice plant per la variabile Produce.
PlantBal[plant, product, month] -> PBal: Produce + Inventory[month-1] + SUM (fromplant:Ship[fromplant, toplant:=plant]) = Sales + Inventory + SUM(toplant: Ship[fromplant:=plant, toplant]);
Sul lato sinistro, dove abbiamo portato tutto quello che sta andando verso l'impianto, aggiungere una sommatoria per sommare tutti i trasporti da ognuno degli altri impianti all'attuale impianto per il vincolo. Nella sommatoria, introdurre la variabile Ship con l'impianto di destinazione prendendo i valori dall'attuale indice plant.
Sul lato destro, dove abbiamo portato tutto quello che esce dall'impianto, aggiungere un'altra sommatoria per sommare insieme tutti i carichi dall'impianto attuale ad ognuno degli altri impianti. Nella sommatoria introdurre la variabile Ship questa volta con l'impianto di partenza prendendo il valore dell'attuale indice plant per il vincolo.
Il prossimo passo sarà risolvere il modello Planning6 scegliendo Solve CPLEX dal menu Run. Se tutto procede bene MPL visualizzerà il messaggio "Optimal Solution Found" "Trovata Soluzione Ottimale". Se c'è una finestra d'errore di messaggio con un errore di sintassi per favore, si controlli e si confronti la formulazione introdotta con il modello dettagliato precedentemente in questa sessione.
Userete la finestra di definizioni del modello ancora come nella Sessione5 per guardare le parti della soluzione che c'interessano. per aprire la finestra di definizioni del modello per il modello Planning6 scegliere Model Definitions dal menu View.
Definizioni del Modello attraverso Finestra ad Albero per il modello Planning6
Per guardare i valori della variabile Produce, si clicchi due volte sull' articolo Produce nell'albero, o si selezioni lo stesso e poi si prema il bottone View. Questo visualizzerà una finestra contenente solo i valori per la variabile Produce come mostrato di sotto.
VARIABLE Produce[plant,product,month] : plant product month Activity Reduced Cost ----------------------------------------------------------- p1 A1 Jan 4300.0 0.0 p1 A1 Feb 4200.0 0.0 p1 A1 Mar 6400.0 0.0 p1 A1 Apr 5300.0 0.0 p1 A2 Jan 1080.0 0.0 p1 A3 Jan 5400.0 0.0 p1 A3 Feb 5220.0 0.0 p1 A3 Mar 4590.0 0.0 p1 A3 Apr 5130.0 0.0 p2 A1 Jan 5100.0 0.0 p2 A1 Feb 6200.0 0.0 p2 A1 Mar 5400.0 0.0 p2 A1 Apr 7600.0 0.0 p2 A2 Jan 6177.3 0.0 p2 A2 Feb 3927.3 0.0 p2 A2 Mar 5931.8 0.0 p2 A2 Apr 3681.8 0.0 p3 A1 Jan 4100.0 0.0 p3 A1 Feb 6100.0 0.0 p3 A1 Mar 4700.0 0.0 p3 A1 Apr 5800.0 0.0 p3 A3 Jan 4166.7 0.0 p3 A3 Feb 1933.3 0.0 p3 A3 Mar 3766.7 0.0 p3 A3 Apr 2733.3 0.0 p4 A1 Jan 3850.0 0.0 p4 A1 Feb 2828.6 0.0 p4 A1 Mar 5300.0 0.0 p4 A1 Apr 4500.0 0.0 p4 A3 Jan 5600.0 0.0 p4 A3 Feb 5200.0 0.0 p4 A3 Mar 4677.3 0.0 p4 A3 Apr 4836.4 0.0 -----------------------------------------------------------
Come potete vedere, la produzione è ora distribuita tra differenti impianti in un modo più redditizio. Alcuni prodotti sono chiaramente prodotti meglio in alcuni impainti dovendo considerare il costo di produzione e il costo di trasporto. Per esempio, il prodotto A2 è prodotto negli impianti p1 e p2, ma non in p3 e p4, mentre il prodotto A3 è prodotto negli impianti p1, p3 e p4. Il prodotto A1 è prodotto nella maniera più economica in tutti gli impianti.
Se si va ancora nelle tre finestre e si apre una finestra per la variabile Ship si avranno i seguenti valori di soluzione:
VARIABLE Ship[product,month,fromplant,toplant] : product month fromplant toplant Activity Reduced Cost ------------------------------------------------------------------------ A2 Mar p2 p4 331.8 0.0 A3 Mar p4 p3 877.3 0.0 A3 Apr p4 p3 736.4 0.0 ------------------------------------------------------------------------
Come potete vedere il modello suggerisce che si trasporti il prodotto A2 dall'impianto p2 all'impianto p4. Allo stesso modo, il prodotto A3 è trasportato dall'impianto p4 e p3. Chiaramente, gli impianti p2 e p4 hanno capacità extra a un costo più basso che può essere usato per produrre beni che gli impianti p4 e p3 necessitano.